package com.abu.manager.service.impl;


import cn.hutool.core.convert.Convert;
import cn.hutool.core.util.StrUtil;
import cn.hutool.crypto.digest.MD5;
import com.abu.common.exception.CRException;
import com.abu.manager.config.mvc.LoginInterceptor;
import com.abu.manager.mapper.ManagerMapper;
import com.abu.manager.pojo.Manager;
import com.abu.manager.pojo.ManagerRole;
import com.abu.manager.pojo.Role;
import com.abu.manager.service.ManagerRoleService;
import com.abu.manager.service.ManagerService;
import com.abu.manager.service.RoleService;
import com.abu.manager.utils.JwtUtils;
import com.abu.manager.vo.ManagerVO;
import com.abu.manager.vo.QueryConditionVO;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import org.apache.commons.lang3.StringUtils;
import org.apache.ibatis.session.SqlSessionException;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.time.LocalDateTime;
import java.util.*;
import java.util.stream.Collectors;

/**
 * <p>
 * 管理员表（超级管理员，楼主） 服务实现类
 * </p>
 *
 * @author 阿布
 * @since 2021-02-03
 */
@Service
public class ManagerServiceImpl extends ServiceImpl<ManagerMapper, Manager> implements ManagerService {

    @Autowired
    private JwtUtils jwtUtils;

    @Value("${jwt.expire}")
    private String expireTime;

    @Autowired
    private RoleService roleService;

    @Autowired
    private ManagerMapper managerMapper;

    @Autowired
    private ManagerRoleService managerRoleService;

    @Override
    public HashMap<String, Object> auth(String managerName, String password) {
//        查询用户是否存在
        QueryWrapper<Manager> queryWrapper = new QueryWrapper<Manager>().eq("mg_name", managerName);
        queryWrapper.select("mg_pwd", "mg_id", "mg_name", "salt", "mg_state","real_name");
        Manager manager = this.getOne(queryWrapper);
        if (manager == null) {
            throw new CRException("用户不存在");
        }
        if (!manager.getMgState()) {
            throw new CRException("用户暂未启用，请联系管理员启用");
        }
//        对用户输入的密码进行加盐加密
        String salt = manager.getSalt();
        String managerMgPwd = manager.getMgPwd();
        String inputMd5Password = MD5.create().digestHex16(password + salt);
//        比对密码是否一致
        if (!StrUtil.equals(managerMgPwd, inputMd5Password)) {
            throw new CRException("用户名或密码有误");
        }
        Long mgId = manager.getMgId();
        String realName = manager.getRealName();
//        生成token信息
        Map<String, String> mapToken = new HashMap<>(2);
        String managerId = Convert.toStr(mgId);
        mapToken.put("managerId", managerId);
        String token = jwtUtils.getToken(mapToken, Convert.toInt(expireTime) * 12);

//        给token添加前缀
        String hasPrefixToken = "ManagerLogin" + token;
//        获取当前用户的权限Id列表
        List<Long> pIdList = this.managerRoleService.queryPIdList(mgId);
//        返回结果集
        HashMap<String, Object> returnDataMap = new HashMap<>(2);
        returnDataMap.put("token", hasPrefixToken);
        returnDataMap.put("realName", realName);
        returnDataMap.put("managerId", managerId);
        returnDataMap.put("pIdList", pIdList);
        return returnDataMap;
    }

    @Override
    public HashMap<String, Object> queryByCondition(QueryConditionVO queryCondition) {
        Long page = queryCondition.getPage();
        Long limit = queryCondition.getLimit();
//       判断分页条件是否为空
        if (page == null) {
            page = 1L;
        }
        if (limit == null) {
            limit = 10L;
        }
        String searchParam = queryCondition.getSearchParam();
        LocalDateTime startTime = queryCondition.getStartTime();
        LocalDateTime endTime = queryCondition.getEndTime();
//        构造查询条件
        QueryWrapper<Manager> queryWrapper = new QueryWrapper<>();
        queryWrapper
                .like(StrUtil.isNotBlank(searchParam), "mg_name", searchParam)
                .or()
                .like(StrUtil.isNotBlank(searchParam), "mg_mobile", searchParam)
                .between((startTime != null && endTime != null), "gmt_create", startTime, endTime)
                .select("mg_id", "mg_name", "mg_mobile", "mg_email", "mg_state", "gmt_create","real_name");
//        分页条件
        Page<Manager> userPage = new Page<>(page, limit);
//        执行查询
        Page<Manager> pageResult = this.page(userPage, queryWrapper);
//        封装结果并返回
        List<Manager> managerList = pageResult.getRecords();
        long total = pageResult.getTotal();
//        获取用户角色名字
        List<ManagerVO> managerVoList = managerList.stream().map(manager -> {
            ManagerVO managerVo = new ManagerVO();
            Long mgId = manager.getMgId();
            Role role = this.roleService.queryRoleByManagerId(mgId);
            BeanUtils.copyProperties(manager, managerVo);
            if (role != null) {
                managerVo.setRoleLevel(role.getRoleLevel()).setRoleName(role.getRoleName());
            }
            return managerVo;
        }).collect(Collectors.toList());
//        封装结果集
        HashMap<String, Object> mapResult = new HashMap<>(2);
        mapResult.put("managerVoList", managerVoList);
        mapResult.put("total", total);
        return mapResult;
    }

    @Override
    @Transactional(rollbackFor = SqlSessionException.class)
    public boolean removeManagerAndRole(Long managerId) {
        boolean removeManagerRoleFlag = this.managerRoleService.remove(new QueryWrapper<ManagerRole>().eq("manager_id", managerId));
        boolean removeManagerFlag = this.removeById(managerId);
        return removeManagerFlag && removeManagerRoleFlag;
    }

    @Override
    @Transactional
    public Boolean deleteBatch(String ids) {
//        判断是否为空
        if (StrUtil.isBlank(ids)) {
            throw new CRException("你还未选中一条数据呢");
        }
        String[] idArray = StrUtil.split(ids, ",");
        List<String> idList = Arrays.asList(idArray);
        boolean batchdeletemflag = this.removeByIds(idList);
        boolean batchdeletemrflag = idList.stream().allMatch(id ->
                this.managerRoleService.remove(new QueryWrapper<ManagerRole>().eq("manager_id", id))
        );
        return batchdeletemflag && batchdeletemrflag;
    }

    @Override
    @Transactional
    public Boolean saveManagerAndRole(ManagerVO managerVo) {
//        查询用户是否存在
        Manager getManager = this.getOne(new QueryWrapper<Manager>().eq("mg_name", managerVo.getMgName()));
        if (getManager != null) {
            throw new CRException("用户已经存在了");
        }
//        对密码进行加盐加密
        String mgPwd = managerVo.getMgPwd();
        String salt = UUID.randomUUID().toString().replace("-", "").substring(0, 5);
//        用户保存
        String newPassword = MD5.create().digestHex16(mgPwd + salt);
        managerVo.setSalt(salt).setMgPwd(newPassword);
//        管理员保存
        boolean saveManagerFlag = this.save(managerVo);
//        添加用户角色信息
        ManagerRole managerRole = new ManagerRole();
        managerRole.setRoleId(managerVo.getRoleId()).setManagerId(managerVo.getMgId());
        boolean saveMRFlag = this.managerRoleService.save(managerRole);
        return saveMRFlag && saveManagerFlag;
    }

    @Override
    public Boolean resetPwd(Long mgId) {
        String salt = "f5yg7";
        String initialPwd = "aaa666";
        String encodedPassword = MD5.create().digestHex16(initialPwd + salt);
        Manager manager = new Manager();
        manager
                .setMgId(mgId)
                .setSalt(salt)
                .setMgPwd(encodedPassword);
        return this.updateById(manager);
    }

    @Override
    public Boolean modifiedPwd(ManagerVO userVo) {
        String newPwd01 = userVo.getNewPwd01();
        String newPwd02 = userVo.getNewPwd02();

        String oldPwd = userVo.getMgPwd();
        String managerId = LoginInterceptor.getManagerId();
//        1.判断两次密码是否一样
        if (!StringUtils.equals(newPwd01, newPwd02)) {
            throw new CRException("输入的两次密码不一致");
        }
//        2.根据id查询用户
        Manager manager = this.getOne(new QueryWrapper<Manager>()
                .eq("mg_id", managerId)
                .select("mg_pwd", "salt")
        );
//        3.验证密码是否一致
        String salt = manager.getSalt();
        String managerMgPwd = manager.getMgPwd();
//        3.1对输入的密码用原来的盐值加密，进行比对
        String dbPwd = MD5.create().digestHex16(oldPwd + salt);
        if (!StringUtils.equals(managerMgPwd, dbPwd)) {
            throw new CRException("原密码不对，请重新输入");
        }
//        4.验证通过，生成新加密的密码，进行更新用户
//        4.1生成盐值
        String newSalt = UUID.randomUUID().toString().replace("-", "").substring(0, 5);
//        4.2对新密码加盐加密
        String newPassword = MD5.create().digestHex16(newPwd02 + newSalt);
        Manager newManager = new Manager();
        newManager
                .setMgId(Long.parseLong(managerId))
                .setMgPwd(newPassword)
                .setSalt(newSalt);
//        5.更新用户
        return this.updateById(newManager);
    }

    @Override
    public ManagerVO queryManagerInfoByManagerId() {
        String idStr = LoginInterceptor.getManagerId();
        Long id = Long.parseLong(idStr);
        return this.managerMapper.selectManagerInfoDetails(id);
    }

    @Override
    public List<Manager> selectInfoListBesidesSuperAdmin() {
        return this.managerMapper.selectInfoListBesidesSuperAdmin();
    }
}
